package cn.cdeden.system.service.impl;

import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.core.utils.page.TableDataInfo;
import cn.cdeden.common.mybatis.core.page.PageQuery;
import cn.cdeden.common.mybatis.validator.QueryHelpMybatisPlus;
import cn.cdeden.resource.api.RemoteFileService;
import cn.cdeden.system.domain.dto.FilesTreeRecycleParam;
import cn.cdeden.system.domain.enums.DeleteTypeEnums;
import cn.cdeden.system.domain.enums.TreeEnum;
import cn.cdeden.system.domain.enums.TreeTypeEnum;
import cn.cdeden.system.domain.vo.FilesTreeRecycleVo;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.undertow.util.BadRequestException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.cdeden.system.mapper.FilesTreeRecycleMapper;
import cn.cdeden.system.domain.FilesTreeRecycle;
import cn.cdeden.system.service.FilesTreeRecycleService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "filesTreeRecycle")
@Slf4j
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class FilesTreeRecycleServiceImpl extends ServiceImpl<FilesTreeRecycleMapper, FilesTreeRecycle> implements FilesTreeRecycleService{

    private final FilesTreeRecycleMapper recycleMapper;

    @DubboReference(check = false)
    private final RemoteFileService remoteFileService;


    @Override
    public TableDataInfo<FilesTreeRecycleVo> selectRecycleAll(FilesTreeRecycleParam param, PageQuery pageable) {
//        Page<Object> build = pageable.build();
//        IPage<FilesTreeRecycle> page = PageUtil.toMybatisPage(pageable);

//        QueryWrapper<FilesTreeRecycle> wrapper = new QueryWrapper<FilesTreeRecycle>();
        QueryWrapper<FilesTreeRecycle> wrapper = QueryHelpMybatisPlus.getPredicate(param);
        wrapper.eq("delete_type", DeleteTypeEnums.DISPLAY.getType());

        if (StringUtils.equalsIgnoreCase( param.getFileTreeType() , TreeEnum.PERSONAL.getType()) ){
            wrapper.eq("create_id", param.getId());
        }else if (StringUtils.equalsIgnoreCase( param.getFileTreeType() , TreeEnum.TEAM.getType())){
            wrapper.eq("team_id", param.getId());
        }else if (StringUtils.equalsIgnoreCase( param.getFileTreeType() , TreeEnum.ENTERPRISE.getType())){
            wrapper.eq("team_id", param.getId());
        }

        if (StringUtils.isNotEmpty(param.getStartTime())){
            DateTime time = DateUtil.parse(param.getStartTime());
//            DateTime time = DateUtil.endOfSecond();
            wrapper.gt("delete_time", time);
        }
        if (param.getEndTime() != null){
            DateTime time = DateUtil.parse(param.getEndTime());
//            DateTime time = DateUtil.endOfSecond(param.getEndTime());
            wrapper.lt("delete_time", time);
        }
        wrapper.orderByDesc("delete_time");


        IPage<FilesTreeRecycle> recycleIPage = recycleMapper.selectPage(pageable.build(),wrapper );
        TableDataInfo<FilesTreeRecycle> build = TableDataInfo.build(recycleIPage);
        TableDataInfo<FilesTreeRecycleVo> filesTreeRecycleVoTableDataInfo = MapstructUtils.convertTableDataInfo(build, FilesTreeRecycleVo.class);
//        List<FilesTreeRecycleVo> treeVoList = ConvertUtil.convertList(recycleIPage.getRecords(), FilesTreeRecycleVo.class);
//        return new PageInfo<>(pageList.getTotal(), treeVoList, pageable.getPageNumber(), pageable.getPageSize());
        return filesTreeRecycleVoTableDataInfo;
    }

    @Override
    public List<FilesTreeRecycle> selectRecycle(String id, List<String> ids, String parentId, String type) throws BadRequestException {
        QueryWrapper<FilesTreeRecycle> wrapper = new QueryWrapper<FilesTreeRecycle>()
            .in("id",ids).eq("file_tree_type",type).eq("delete_type",DeleteTypeEnums.DISPLAY.getType());
        List<FilesTreeRecycle> recycleList = this.list(wrapper);

        if (CollectionUtils.isEmpty(recycleList) && ids.size() != recycleList.size()  ){
            throw new BadRequestException("错误的恢复");
        }
        recycleList.forEach(tree -> {
            tree.setParentId(parentId);
            List<FilesTreeRecycle> select = select(String.valueOf(tree.getFileTreeId()), tree.getFileTreeType(), id);
            tree.setSonDataList(select);
            List<Long> collect = select.stream().map(FilesTreeRecycle::getId).collect(Collectors.toList());
            tree.setIds( new HashSet<>(collect));

        });

        return recycleList;
    }

    @Override
    public boolean deleteAll() {
        List<FilesTreeRecycle> recycleList = this.list();

        if (CollectionUtils.isEmpty(recycleList)){
            return false;
        }


        return  deleteData(recycleList);
    }

    @Override
    public boolean delete(String type) {
        LambdaQueryWrapper<FilesTreeRecycle> wrapper = new LambdaQueryWrapper<FilesTreeRecycle>()
            .eq(FilesTreeRecycle::getFileTreeType, type);
        List<FilesTreeRecycle> recycleList = this.list(wrapper);

        if (CollectionUtils.isEmpty(recycleList)){
            return false;
        }
        return  deleteData(recycleList);
    }


    public boolean deleteData(List<FilesTreeRecycle> recycleList ) {
        Map<String, Set<String>> map = new HashMap<>();
        List<Long> ids = new ArrayList<>();

        recycleList.forEach(filesTreeRecycle -> {
            ids.add(filesTreeRecycle.getId());
            String storageType = filesTreeRecycle.getStorageType();
            String storageId = filesTreeRecycle.getStorageId();
            String type = filesTreeRecycle.getType();
            if (StringUtils.equalsIgnoreCase(type,TreeTypeEnum.FILE.getType())){
                if (map.containsKey(storageType)){
                    Set<String> strings = map.get(storageType);
                    strings.add(storageId);
                }else {
                    HashSet<String> set = new HashSet<>();
                    set.add(storageId);
                    map.put(storageType,set);
                }

            }
        });

//        删除数据
        this.removeByIds(ids);
//        删除实体文件
        map.forEach((key, v) -> {
            //删除文件
            remoteFileService.deleteWithValidByIds(v.stream().map(Long::valueOf).collect(Collectors.toList()), false);
            //删除最近查看记录

//            storageService.deleteBatch(v, StorageTypeEnum.find(key));
        });
        return true;
    }




    public List<FilesTreeRecycle> select(String parent_id, String type , String id) {

        QueryWrapper<FilesTreeRecycle> wrapper = new QueryWrapper<FilesTreeRecycle>()
            .in("parent_id",parent_id)
//                .eq("","")
            .eq("file_tree_type",type)
            .eq("delete_type",DeleteTypeEnums.NO_DISPLAY.getType());
        if (StringUtils.equalsIgnoreCase(TreeEnum.PERSONAL.getType(),type)){
            wrapper.eq("create_id",id);
        }else if (StringUtils.equalsIgnoreCase(TreeEnum.TEAM.getType(),type)){
            wrapper.eq("team_id",id);
        }else if (StringUtils.equalsIgnoreCase(TreeEnum.ENTERPRISE.getType(),type)){
            wrapper.eq("team_id",id);
        }

        List<FilesTreeRecycle> recycleList = this.list(wrapper);
        if (CollectionUtils.isNotEmpty(recycleList)){
            recycleList.forEach(recycle -> {
                if (StringUtils.equalsIgnoreCase(TreeTypeEnum.FOLDER.getType(),recycle.getType())){
                    List<FilesTreeRecycle> select = select(String.valueOf(recycle.getFileTreeId()), type, id);
                    recycle.setSonDataList(select);
                    List<Long> collect = select.stream().map(FilesTreeRecycle::getId).collect(Collectors.toList());
                    recycle.setIds( new HashSet<>(collect));
                }

            });
        }

        return recycleList;
    }



}
